package com.xu.cloud.common.runner;

import com.baomidou.mybatisplus.core.MybatisPlusVersion;
import com.xu.cloud.common.constant.Constant;
import com.xu.cloud.common.thread.NamedThreadFactory;
import com.xu.cloud.common.util.IpUtil;
import com.xu.cloud.common.util.XuCloudVersion;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringBootVersion;
import org.springframework.boot.ansi.AnsiColor;
import org.springframework.boot.ansi.AnsiOutput;
import org.springframework.boot.system.SystemProperties;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.SpringVersion;
import org.springframework.core.env.Environment;
import org.springframework.util.ClassUtils;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 打印Banner
 *
 * @author xuguan
 * @since 2024/6/28
 */
public class XuCloudReadyBannerPrinter implements ApplicationRunner, EnvironmentAware {

    private static final String[] BANNER = {
            "",
            "_  _ _  _    ____ _    ____ _  _ ___",
            " \\/  |  | __ |    |    |  | |  | |  \\",
            "_/\\_ |__|    |___ |___ |__| |__| |__/"
    };

    private static final String JDK_VERSION = "Java Version: ";
    public static final String SPRING_VERSION = "Spring Version: ";
    public static final String SPRING_BOOT_VERSION = "SpringBoot Version: ";
    public static final String MYBATIS_PLUS_VERSION = "MybatisPlus Version: ";
    public static final String XU_CLOUD_VERSION = "XuCloud Version: ";
    public static final String SPRING_APPLICATION_NAME = "Spring Application Name: ";
    public static final String SPRING_PROFILES_ACTIVE = "Spring Profiles Active: ";
    public static final String APPLICATION_URL_ADDRESS = "Application Url Address: ";
    private Environment environment;
    public static final String THREAD_PREFIX = "async-xu-cloud-banner-printer-";

    @Override
    public void run(ApplicationArguments args) throws Exception {
        final ExecutorService executorService = Executors.newSingleThreadExecutor(new NamedThreadFactory(THREAD_PREFIX));
        executorService.submit(() -> {
            try {
                // 线程休眠1秒保证最后打印banner
                TimeUnit.SECONDS.sleep(1L);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            StringBuilder banner = new StringBuilder();
            for (String line : BANNER) {
                banner.append(line).append(Constant.LF);
            }

            final String jdkVersion = SystemProperties.get("java.version");
            if (jdkVersion != null) {
                banner.append(AnsiOutput.toString(AnsiColor.DEFAULT, JDK_VERSION, AnsiColor.BRIGHT_GREEN, jdkVersion)).append(Constant.LF);
            }

            banner.append(AnsiOutput.toString(AnsiColor.DEFAULT, SPRING_VERSION, AnsiColor.BRIGHT_GREEN, SpringVersion.getVersion())).append(Constant.LF);
            banner.append(AnsiOutput.toString(AnsiColor.DEFAULT, SPRING_BOOT_VERSION, AnsiColor.BRIGHT_GREEN, SpringBootVersion.getVersion())).append(Constant.LF);
            if (ClassUtils.isPresent("com.baomidou.mybatisplus.core.MybatisPlusVersion", this.getClass().getClassLoader())) {
                banner.append(AnsiOutput.toString(AnsiColor.DEFAULT, MYBATIS_PLUS_VERSION, AnsiColor.BRIGHT_GREEN, MybatisPlusVersion.getVersion())).append(Constant.LF);
            }
            banner.append(AnsiOutput.toString(AnsiColor.DEFAULT, XU_CLOUD_VERSION, AnsiColor.BRIGHT_GREEN, XuCloudVersion.getVersion())).append(Constant.LF);

            final String applicationName = environment.getProperty("spring.application.name");
            if (applicationName != null) {
                banner.append(AnsiOutput.toString(AnsiColor.DEFAULT, SPRING_APPLICATION_NAME, AnsiColor.BRIGHT_GREEN, applicationName)).append(Constant.LF);
            }

            final String profileActive = environment.getProperty("spring.profiles.active", "default");
            banner.append(AnsiOutput.toString(AnsiColor.DEFAULT, SPRING_PROFILES_ACTIVE, AnsiColor.BRIGHT_GREEN, profileActive)).append(Constant.LF);

            String port = environment.getProperty("server.port");
            if (port == null) {
                port = "8080";
            }
            banner.append(AnsiOutput.toString(AnsiColor.DEFAULT, APPLICATION_URL_ADDRESS, AnsiColor.DEFAULT, "http://" + IpUtil.getLocalIp() + ":" + port)).append(Constant.LF);

            System.out.println(banner);
        });
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}
